package com.seven.restaurant.exception;

import com.seven.restaurant.util.ResponseEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * <p>全局异常处理类</p>
 * @author BaiBan
 * @since 2022/7/11
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NullPointerException.class)
    public ResponseEntity<Object> businessExceptionHandler(NullPointerException e) {
        log.info("{}", e.getMessage());
        return ResponseEntity.fail();
    }

    /**
     * 全局错误提示
     * @param e
     * @return
     */
    @ExceptionHandler(GlobalException.class)
    public ResponseEntity<Object> businessExceptionHandler(GlobalException e) {
        return ResponseEntity.fail(e.getCode());
    }

    /**
     * 参数错误处理拦截器
     * @param e {@link ValidationException}
     * @return 错误信息
     */
    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<?> businessExceptionHandler(ValidationException e) {
        log.info("{}", e.getMessage());
        InfoCode code = InfoCode.VALIDATION_ERROR;
        return ResponseEntity.fail(code.getCode(), code.getMessage() + e.getMessage());
    }


    /**
     * 数据效验错误处理拦截器
     * json类型 对象接收异常处理
     * 参数为实体类
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResponseEntity<Object> handleValidException(MethodArgumentNotValidException e) {
        // 从异常对象中拿到非法参数信息
        String message = e.getBindingResult()
                .getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(";"));
        return ResponseEntity.fail(520, message);
    }

    /**
     * 数据效验错误处理拦截器
     * form类型 多参数接收异常处理
     * 参数为单个参数或多个参数
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException e) {
        // 从异常对象中拿到非法参数信息
        String message =  e.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.joining(";"));
        return ResponseEntity.fail(520, message);
    }

    /**
     * 数据效验错误处理拦截器
     * form类型 对象接收异常处理
     * 参数为实体类
     */
    @ExceptionHandler(value = BindException.class)
    public ResponseEntity<Object> handleConstraintViolationException(BindException e) {
        // 从异常对象中拿到非法参数信息
        String message = e.getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(";"));
        return ResponseEntity.fail(520, message);
    }
}